package com.share.payment.service.impl;

import com.alibaba.fastjson2.JSON;
import com.share.common.core.domain.R;
import com.share.common.core.exception.ServiceException;
import com.share.payment.config.WxPayV3Properties;
import com.share.payment.domain.CreateWxPaymentForm;
import com.share.payment.domain.PaymentInfo;
import com.share.payment.domain.WxPrepayVo;
import com.share.payment.service.IPaymentInfoService;
import com.share.payment.service.IWxPayService;
import com.share.payment.utils.RequestUtils;
import com.share.user.api.RemoteUserInfoService;
import com.share.user.api.domain.UserInfo;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
@Slf4j
@RequiredArgsConstructor
public class WxPayServiceImpl implements IWxPayService {

    private final IPaymentInfoService paymentInfoService;
    private final RemoteUserInfoService remoteUserInfoService;
    private final WxPayV3Properties wxPayV3Properties;
    private final RSAAutoCertificateConfig rsaAutoCertificateConfig;

    @Override
    public WxPrepayVo createWxPayment(CreateWxPaymentForm createWxPaymentForm) {
        String orderNo = createWxPaymentForm.getOrderNo();
        log.info("开始创建微信支付预订单，订单号: {}", orderNo);

        try {
            // 保存支付记录并获取支付信息
            PaymentInfo paymentInfo = paymentInfoService.savePaymentInfo(orderNo);
            log.info("支付记录已保存，订单号: {}, 金额: {}", orderNo, paymentInfo.getAmount());

            // 获取用户微信OpenID
            R<UserInfo> userInfoResult = remoteUserInfoService.getUserInfo(paymentInfo.getUserId());
            if (userInfoResult == null || userInfoResult.getData() == null) {
                log.error("获取用户信息失败，订单号: {}", orderNo);
                throw new ServiceException("获取用户信息失败");
            }
            if (R.FAIL == userInfoResult.getCode()) {
                log.error("获取用户信息失败，订单号: {}, 错误信息: {}", orderNo, userInfoResult.getMsg());
                throw new ServiceException(userInfoResult.getMsg());
            }
            String openid = userInfoResult.getData().getWxOpenId();
            log.info("获取用户OpenID成功，订单号: {}, OpenID: {}", orderNo, openid);

            // 构建微信支付服务
            JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

            // 创建预支付请求
            PrepayRequest request = new PrepayRequest();

            // 设置金额（转换为分，使用BigDecimal避免精度问题）
            Amount amount = new Amount();
            amount.setTotal(paymentInfo.getAmount().multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
            request.setAmount(amount);

            // 设置基本信息
            request.setAppid(wxPayV3Properties.getAppid());
            request.setMchid(wxPayV3Properties.getMerchantId());
            request.setDescription(paymentInfo.getContent());
            request.setNotifyUrl(wxPayV3Properties.getNotifyUrl());
            request.setOutTradeNo(orderNo);

            // 设置支付者信息
            Payer payer = new Payer();
            payer.setOpenid(openid);
            request.setPayer(payer);

            // 执行预下单请求
            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
            log.info("微信支付预下单成功，订单号: {}", orderNo);

            // 转换返回结果
            WxPrepayVo wxPrepayVo = new WxPrepayVo();
            BeanUtils.copyProperties(response, wxPrepayVo);
            wxPrepayVo.setTimeStamp(response.getTimeStamp());

            log.info("微信支付预订单创建完成，订单号: {}", orderNo);
            return wxPrepayVo;

        } catch (IllegalArgumentException e) {
            log.error("订单号不存在，订单号: {}", orderNo, e);
            throw new ServiceException("订单号不存在");
        } catch (ServiceException e) {
            log.error("业务异常，订单号: {}, 错误信息: {}", orderNo, e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("微信支付预下单异常，订单号: {}", orderNo, e);
            throw new ServiceException("微信下单异常");
        }
    }

    /**
     * 微信支付异步通知接口
     */
    @Override
    public void wxnotify(HttpServletRequest request) {
        // 1. 回调通知的验签与解密
        // 从request头信息获取微信支付回调的关键参数
        // HTTP 头 Wechatpay-Signature：微信支付的签名
        // HTTP 头 Wechatpay-Nonce：随机字符串
        // HTTP 头 Wechatpay-Timestamp：时间戳
        // HTTP 头 Wechatpay-Serial：证书序列号
        // HTTP 头 Wechatpay-Signature-Type：签名类型
        // HTTP 请求体 body：回调通知的内容，注意需使用原始报文进行验签
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String signature = request.getHeader("Wechatpay-Signature");
        String requestBody = RequestUtils.readData(request);
        log.info("wechatPaySerial：{}", wechatPaySerial);
        log.info("nonce：{}", nonce);
        log.info("timestamp：{}", timestamp);
        log.info("signature：{}", signature);
        log.info("requestBody：{}", requestBody);

        // 2. 构造 RequestParam 对象，用于后续的签名验证
        RequestParam requestParam = new RequestParam.Builder().serialNumber(wechatPaySerial).nonce(nonce).signature(signature).timestamp(timestamp).body(requestBody).build();

        // 3. 初始化 NotificationParser，用于处理微信支付的通知
        // 使用 RSA 自动证书配置，确保证书的有效性和安全性
        NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);

        // 4. 以支付通知回调为例，进行验签、解密并转换成 Transaction 对象
        // 这一步会验证签名的有效性，并解密通知内容
        Transaction transaction = parser.parse(requestParam, Transaction.class);
        log.info("成功解析：{}", JSON.toJSONString(transaction));

        // 5. 检查交易状态，处理支付成功的业务逻辑
        if (null != transaction && transaction.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
            // 调用支付信息服务更新支付状态
            // 这里会根据交易信息更新订单状态、记录支付日志等业务操作
            paymentInfoService.updatePaymentStatus(transaction);
        }
    }

    /**
     * 支付状态查询
     */
    @Override
    public Transaction queryPayStatus(String orderNo) {
        // 构建微信支付服务，使用自动证书配置
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();

        // 创建查询订单请求，设置商户ID和商户订单号
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(wxPayV3Properties.getMerchantId());
        queryRequest.setOutTradeNo(orderNo);

        try {
            // 调用微信支付API查询订单状态
            Transaction result = service.queryOrderByOutTradeNo(queryRequest);
            log.info("订单查询成功，订单号: {}, 查询结果: {}", orderNo, JSON.toJSONString(result));
            return result;
        } catch (ServiceException e) {
            // 处理API返回失败的情况，例如订单不存在等
            log.error("订单查询失败，订单号: {}, 错误码: {}, 错误信息: {}", orderNo, e.getCode(), e.getMessage());

            // 根据不同错误码可以进行不同处理，这里简单返回null
            // 实际应用中可以根据业务需求进行更详细的错误处理
            return null;
        }
    }
}